import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns


def analyze_stance_distribution():
    # ==================== 配置参数 ====================
    INPUT_EXCEL = r"C:\Users\23248\PycharmProjects\stance\StanceDetectionLab\lab2\test_data\output.xlsx"
    OUTPUT_IMG = 'topic_stance_distribution_optimized.png'
    STANCE_ORDER = ['支持', '反对', '中立']
    PALETTE = {'支持': '#4CAF50', '反对': '#F44336', '中立': '#FFC107'}
    SPECIFIC_TOPIC = "胡锡进谈虐猫事件"  # 指定需要优先展示的话题

    # ==================== 中文显示配置 ====================
    plt.rcParams.update({
        'font.family': 'SimSun',
        'axes.unicode_minus': False
    })

    try:
        # ==================== 数据加载与处理 ====================
        df = pd.read_excel(INPUT_EXCEL)
        df['stance'] = df['stance'].str.strip().str.replace(' ', '').str.replace('中立方', '中立')
        df = df[df['stance'].isin(STANCE_ORDER)]

        # ==================== 智能排序逻辑 ====================
        # 确保指定话题排在首位，其他按总讨论量降序排列
        topic_counts = df.groupby('topic').size()
        sorted_topics = topic_counts.sort_values(ascending=False).index.tolist()

        if SPECIFIC_TOPIC in sorted_topics:
            sorted_topics.remove(SPECIFIC_TOPIC)
            sorted_topics.insert(0, SPECIFIC_TOPIC)

        # 生成排序后的交叉表
        stance_dist = pd.crosstab(df['topic'], df['stance']).reindex(sorted_topics)[STANCE_ORDER]

        print("排序后的分布统计：")
        print(stance_dist)

        # ==================== 可视化优化 ====================
        plt.figure(figsize=(18, 9))  # 增大画布尺寸

        ax = stance_dist.plot(kind='bar',
                              width=0.75,
                              color=PALETTE,
                              edgecolor='black',
                              linewidth=0.8,
                              rot=25)  # 调整标签角度

        # 动态设置y轴上限
        max_value = stance_dist.max().max()
        plt.ylim(0, max_value * 1.15)  # 留出25%空间

        # 智能数值标签
        for p in ax.patches:
            height = p.get_height()
            # if height > max_value * 0.8:  # 高柱子标签内嵌显示
            #     ax.annotate(f"{height:.0f}",
            #                 (p.get_x() + p.get_width() / 2, height * 0.95),
            #                 ha='center', va='top',
            #                 fontsize=10, color='white')
            # else:  # 普通高度标签顶部显示
            ax.annotate(f"{height:.0f}",
                        (p.get_x() + p.get_width() / 2, height),
                        ha='center', va='bottom',
                        fontsize=10,
                        xytext=(0, 3),
                        textcoords='offset points')

        # 图表装饰
        plt.title('热点事件立场分布分析', fontsize=18, pad=25)
        plt.xlabel('', fontsize=14)
        plt.ylabel('评论数量', fontsize=14, labelpad=15)

        # 优化x轴标签
        ax.set_xticklabels(stance_dist.index,
                           rotation=25,
                           ha='right',
                           rotation_mode='anchor',
                           fontsize=12)

        # 图例
        ax.legend(title='立场分布',
                  labels=[f"{k}（共{v}次）" for k, v in stance_dist.sum().items()],
                  loc='upper right',  # 调整位置至图表内部右上角
                  edgecolor='#CCCCCC',  # 边框颜色
                  fontsize=10,  # 适当缩小字号
                  title_fontsize=12,  # 保持标题字号
                  facecolor='white',  # 背景色
                  bbox_to_anchor=(0.98, 0.98))  # 微调位置避免遮挡

        plt.grid(axis='y', alpha=0.3)
        plt.subplots_adjust(left=0.1, right=0.82, bottom=0.15)  # 调整边距
        plt.savefig(OUTPUT_IMG, dpi=300, bbox_inches='tight')
        print(f"\n图表已保存至：{OUTPUT_IMG}")
        plt.show()

    except Exception as e:
        print(f"执行出错：{str(e)}")


if __name__ == "__main__":
    analyze_stance_distribution()